package com.mo.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtUtils {
    /**
     * 生成 JWT Token
     *
     * @param subject 可以根据需求携带其他信息
     * @param claims  可选的自定义声明（如角色、权限等）
     * @return JWT Token
     */
    public String generateToken(String subject, Map<String, Object> claims) {
        // 使用 HMAC SHA-256 算法进行签名
        Algorithm algorithm = Algorithm.HMAC256(JWTConstant.JWT_SECRET_KEY);
        JWTCreator.Builder jwtBuilder = JWT.create()
                // 设置主题（通常是唯一的，ID或者用户名）
                .withSubject(subject)
                // 设置签发时间
                .withIssuedAt(new Date())
                .withExpiresAt(new Date(System.currentTimeMillis() + JWTConstant.JWT_EXPIRATION_TIME)); // 设置过期时间

        // 添加自定义的 claims（如果有）
        if (claims != null) {
            for (Map.Entry<String, Object> entry : claims.entrySet()) {
                jwtBuilder.withClaim(entry.getKey(), entry.getValue().toString());
            }
        }

        return jwtBuilder.sign(algorithm); // 签名并生成 Token
    }

    /**
     * 解析 JWT Token，获取 DecodedJWT 对象
     *
     * @param token JWT Token
     * @return DecodedJWT 对象
     */
    private DecodedJWT decodeToken(String token) {
        Algorithm algorithm = Algorithm.HMAC256(JWTConstant.JWT_SECRET_KEY);
        return JWT.require(algorithm)
                .build()
                .verify(token);
    }

    /**
     * 获取 Token 中的主题（Subject）
     *
     * @param token JWT Token
     * @return 主题（Subject）
     */
    public String getSubject(String token) {
        DecodedJWT decodedJWT = decodeToken(token);
        return decodedJWT.getSubject();
    }

    /**
     * 获取 Token 中的所有自定义声明（Claims）
     *
     * @param token JWT Token
     * @return 自定义声明（Claims）
     */
    public Map<String, Object> getClaims(String token) {
        DecodedJWT decodedJWT = decodeToken(token);
        Map<String, Object> claimsMap = new HashMap<>();
        Map<String, Claim> claims = decodedJWT.getClaims();
        for (Map.Entry<String, Claim> entry : claims.entrySet()) {
            Claim claim = entry.getValue();
            claimsMap.put(entry.getKey(), claim.as(Object.class));
        }
        return claimsMap;
    }

    /**
     * 获取 Token 中指定的自定义声明
     *
     * @param token    JWT Token
     * @param claimKey 声明的 key
     * @return 声明的 value
     */
    public String getClaim(String token, String claimKey) {
        DecodedJWT decodedJWT = decodeToken(token);
        return decodedJWT.getClaim(claimKey).asString();
    }

    /**
     * 获取 Token 中的过期时间
     *
     * @param token JWT Token
     * @return 过期时间
     */
    public Date getExpirationDate(String token) {
        DecodedJWT decodedJWT = decodeToken(token);
        return decodedJWT.getExpiresAt();
    }

    /**
     * 校验 Token 是否过期
     *
     * @param token JWT Token
     * @return 是否过期
     */
    public boolean isTokenExpired(String token) {
        Date expirationDate = getExpirationDate(token);
        return expirationDate.before(new Date());
    }

    /**
     * 校验 Token 是否有效（是否已过期）
     *
     * @param token JWT Token
     * @return 是否有效
     */
    public boolean validateToken(String token) {
        return !isTokenExpired(token);
    }

    /**
     * 刷新 Token（重新生成一个新的 Token，通常用于延长过期时间）
     *
     * @param token 旧的 Token
     * @return 新的 Token
     */
    public String refreshToken(String token) {
        if (validateToken(token)) {
            String subject = getSubject(token);
            Map<String, Object> claims = getClaims(token);
            return generateToken(subject, claims);
        }
        return null;
    }
}